﻿/*
** Haaf's Game Engine 1.5
** Copyright (C) 2003-2004, Relish Games
** hge.relishgames.com
**
** hgeAnimation helper class implementation
*/


module core.hgeanim;

private	import		core.hgeall;
private	import		std.c.math;




const HGEANIM_FWD			=0;
const HGEANIM_REV			=1;
const HGEANIM_PINGPONG		=2;
const HGEANIM_NOPINGPONG	=0;
const HGEANIM_LOOP			=4;
const HGEANIM_NOLOOP		=0;


/*
** HGE Animation class
*/
class hgeAnimation :  hgeSprite
{
public:
	this(HTEXTURE tex, int nframes, float FPS, float x, float y, float w, float h)
	{
		super(tex,x,y,w,h);
		fSinceLastFrame=-1.0f;
		fSpeed=1.0f/FPS;
		bPlaying=false;
		nFrames=nframes;

		Mode=HGEANIM_FWD | HGEANIM_LOOP;
		nDelta=1;
		SetFrame(0);
	}


	this(in hgeAnimation anim)
	{	super(anim);
		// Copy hgeAnimation parameters: 
		this.bPlaying        = anim.bPlaying; 
		this.fSpeed          = anim.fSpeed; 
		this.fSinceLastFrame = anim.fSinceLastFrame;
		this.Mode            = anim.Mode;
		this.nDelta          = anim.nDelta;
		this.nFrames         = anim.nFrames;
		this.nCurFrame       = anim.nCurFrame;
	}


	
	
	
	void		Play()
	{
		bPlaying=true;
		fSinceLastFrame=-1.0f;
		if(Mode & HGEANIM_REV) { nDelta=-1; SetFrame(nFrames-1); }
		else { nDelta=1; SetFrame(0); }
	}


	
	void		Stop() 		{ bPlaying=false; }
	void		Resume() 	{ bPlaying=true; }
	void		Update(float fDeltaTime)
		{
			if(!bPlaying) return;

			if(fSinceLastFrame == -1.0f) fSinceLastFrame=0.0f;
			else fSinceLastFrame += fDeltaTime;

			while(fSinceLastFrame >= fSpeed)
			{
				fSinceLastFrame -= fSpeed;

				if(nCurFrame+nDelta == nFrames)
				{
					switch(Mode)
					{
						case HGEANIM_FWD:
						case HGEANIM_REV | HGEANIM_PINGPONG:
							bPlaying=false;
							break;

						case HGEANIM_FWD | HGEANIM_PINGPONG:
						case HGEANIM_FWD | HGEANIM_PINGPONG | HGEANIM_LOOP:
						case HGEANIM_REV | HGEANIM_PINGPONG | HGEANIM_LOOP:
							nDelta=-nDelta;
							break;
					}
				}
				else if(nCurFrame+nDelta < 0)
				{
					switch(Mode)
					{
						case HGEANIM_REV:
						case HGEANIM_FWD | HGEANIM_PINGPONG:
							bPlaying=false;
							break;

						case HGEANIM_REV | HGEANIM_PINGPONG:
						case HGEANIM_REV | HGEANIM_PINGPONG | HGEANIM_LOOP:
						case HGEANIM_FWD | HGEANIM_PINGPONG | HGEANIM_LOOP:
							nDelta=-nDelta;
							break;
						default: break;
					}
				}

				if(bPlaying) SetFrame(nCurFrame+nDelta);
			}
		}

	
	bool		IsPlaying()  	{ return bPlaying; }

	void		SetTextureRect(float x1, float y1, float x2, float y2) { super.SetTextureRect(x1,y1,x2,y2); SetFrame(nCurFrame); }
	void		SetMode(int mode)
				{
					Mode=mode;
					if(mode & HGEANIM_REV) { nDelta=-1; SetFrame(nFrames-1); }
					else { nDelta=1; SetFrame(0); }
				}


	
	void		SetSpeed(float FPS) { fSpeed=1.0f/FPS; }
	void		SetFrame(int n)
			{
				float tx1, ty1, tx2, ty2;
				bool bX=bXFlip, bY=bYFlip;
				int ncols = cast(int)(tex_width) / cast(int)(width);


				n=n%nFrames;
				if(n<0) n=nFrames+n;
				nCurFrame=n;

				// calculate texture coords for frame n
				ty1 = ty;
				tx1 = tx + n*width;
				if(tx1 > tex_width-width)
				{
					n -= cast(int)(tex_width-tx) / cast(int)(width);
					tx1 = width * (n%ncols);
					ty1 += height * (1 + n/ncols);
				}

				tx2 = tx1 + width;
				ty2 = ty1 + height;

				tx1 /= tex_width;
				ty1 /= tex_height;
				tx2 /= tex_width;
				ty2 /= tex_height;

				quad.v[0].tx=tx1; quad.v[0].ty=ty1;
				quad.v[1].tx=tx2; quad.v[1].ty=ty1;
				quad.v[2].tx=tx2; quad.v[2].ty=ty2;
				quad.v[3].tx=tx1; quad.v[3].ty=ty2;

				bXFlip=false; bYFlip=false;
				SetFlip(bX,bY);
			}


	
	void		SetFrames(int n) { nFrames=n; }

	int			GetMode()   { return Mode; }
	float		GetSpeed()   { return 1.0f/fSpeed; }
	int			GetFrame() 	 { return nCurFrame; }
	int			GetFrames()  { return nFrames; }

private:
//	this(){};

	bool		bPlaying;

	float		fSpeed;
	float		fSinceLastFrame;

	int			Mode;
	int			nDelta;
	int			nFrames;
	int			nCurFrame;
};



